﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel.DataAnnotations;
using System.Collections;

namespace NetFrameworkExtensions.DataLayer.EF4
{
  public abstract class HierarchicalData<TIdentified, TIdentifier> :
    IdentifiedData<TIdentified, TIdentifier>,
    IHierarchicalData<TIdentified, TIdentifier>
    where TIdentified : HierarchicalData<TIdentified, TIdentifier>
    where TIdentifier : struct, IEquatable<TIdentifier>
  {
    public virtual TIdentifier? ParentId { get; set; }
    [ForeignKey("ParentId")]
    [InverseProperty("Children")]
    public virtual TIdentified Parent { get; set; }

    [InverseProperty("Parent")]
    public virtual IList<TIdentified> Children { get; set; }

    [NotMapped]
    object IHierarchicalData.ParentId
    {
      get
      {
        return ParentId;
      }
      set
      {
        ParentId = (TIdentifier)value;
      }
    }

    [NotMapped]
    object IHierarchicalData.Parent
    {
      get
      {
        return Parent;
      }
      set
      {
        Parent = (TIdentified)value;
      }
    }

    [NotMapped]
    IList IHierarchicalData.Children
    {
      get
      {
        return (IList)Children;
      }
      set
      {
        Children = (IList<TIdentified>)value;
      }
    }
  }

  public abstract class IdentityHierarchicalData<TIdentified, TIdentifier> :
    IdentityIdentifiedData<TIdentified, TIdentifier>,
    IHierarchicalData<TIdentified, TIdentifier>
    where TIdentified : IdentityHierarchicalData<TIdentified, TIdentifier>
    where TIdentifier : struct, IEquatable<TIdentifier>
  {
    public virtual TIdentifier? ParentId { get; set; }
    [ForeignKey("ParentId")]
    [InverseProperty("Children")]
    public virtual TIdentified Parent { get; set; }

    [InverseProperty("Parent")]
    public virtual IList<TIdentified> Children { get; set; }

    [NotMapped]
    object IHierarchicalData.ParentId
    {
      get
      {
        return ParentId;
      }
      set
      {
        ParentId = (TIdentifier)value;
      }
    }

    [NotMapped]
    object IHierarchicalData.Parent
    {
      get
      {
        return Parent;
      }
      set
      {
        Parent = (TIdentified)value;
      }
    }

    [NotMapped]
    IList IHierarchicalData.Children
    {
      get
      {
        return (IList)Children;
      }
      set
      {
        Children = (IList<TIdentified>)value;
      }
    }
  }
}
